+Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkkeys.c: include gdkkeysysms.h if
+ compiling gdk_keyval_convert_case.
+
+ * gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
+ <Control>Tab <Control><Shift>Tab to cycle between
+ all menu bars in a toplevel once one is up.
+
+ * tests/testgtk.c: Add a second menubar, this
+ example is already full of crack anyways.
+
+ * gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
+ unhandled events up to the parent menu shell.
+
+ * gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
+ pop up the menu if the parent menu shell is still active.
+
+ * gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
+ old_focus argument, export privately.
+
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.
+Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkkeys.c: include gdkkeysysms.h if
+ compiling gdk_keyval_convert_case.
+
+ * gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
+ <Control>Tab <Control><Shift>Tab to cycle between
+ all menu bars in a toplevel once one is up.
+
+ * tests/testgtk.c: Add a second menubar, this
+ example is already full of crack anyways.
+
+ * gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
+ unhandled events up to the parent menu shell.
+
+ * gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
+ pop up the menu if the parent menu shell is still active.
+
+ * gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
+ old_focus argument, export privately.
+
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.
+Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkkeys.c: include gdkkeysysms.h if
+ compiling gdk_keyval_convert_case.
+
+ * gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
+ <Control>Tab <Control><Shift>Tab to cycle between
+ all menu bars in a toplevel once one is up.
+
+ * tests/testgtk.c: Add a second menubar, this
+ example is already full of crack anyways.
+
+ * gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
+ unhandled events up to the parent menu shell.
+
+ * gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
+ pop up the menu if the parent menu shell is still active.
+
+ * gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
+ old_focus argument, export privately.
+
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.
+Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkkeys.c: include gdkkeysysms.h if
+ compiling gdk_keyval_convert_case.
+
+ * gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
+ <Control>Tab <Control><Shift>Tab to cycle between
+ all menu bars in a toplevel once one is up.
+
+ * tests/testgtk.c: Add a second menubar, this
+ example is already full of crack anyways.
+
+ * gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
+ unhandled events up to the parent menu shell.
+
+ * gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
+ pop up the menu if the parent menu shell is still active.
+
+ * gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
+ old_focus argument, export privately.
+
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.
+Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkkeys.c: include gdkkeysysms.h if
+ compiling gdk_keyval_convert_case.
+
+ * gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
+ <Control>Tab <Control><Shift>Tab to cycle between
+ all menu bars in a toplevel once one is up.
+
+ * tests/testgtk.c: Add a second menubar, this
+ example is already full of crack anyways.
+
+ * gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
+ unhandled events up to the parent menu shell.
+
+ * gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
+ pop up the menu if the parent menu shell is still active.
+
+ * gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
+ old_focus argument, export privately.
+
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.
+Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkkeys.c: include gdkkeysysms.h if
+ compiling gdk_keyval_convert_case.
+
+ * gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
+ <Control>Tab <Control><Shift>Tab to cycle between
+ all menu bars in a toplevel once one is up.
+
+ * tests/testgtk.c: Add a second menubar, this
+ example is already full of crack anyways.
+
+ * gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
+ unhandled events up to the parent menu shell.
+
+ * gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
+ pop up the menu if the parent menu shell is still active.
+
+ * gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
+ old_focus argument, export privately.
+
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.
+Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
+
+ * gdk/gdkkeys.c: include gdkkeysysms.h if
+ compiling gdk_keyval_convert_case.
+
+ * gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
+ <Control>Tab <Control><Shift>Tab to cycle between
+ all menu bars in a toplevel once one is up.
+
+ * tests/testgtk.c: Add a second menubar, this
+ example is already full of crack anyways.
+
+ * gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
+ unhandled events up to the parent menu shell.
+
+ * gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
+ pop up the menu if the parent menu shell is still active.
+
+ * gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
+ old_focus argument, export privately.
+
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.
*/
#ifndef HAVE_XCONVERTCASE
+#include "gdkkeysyms.h"
+
/* compatibility function from X11R6.3, since XConvertCase is not
* supplied by X11R5.
*/
GtkDirectionType direction);
static void gtk_container_real_set_focus_child (GtkContainer *container,
GtkWidget *widget);
-static GList * gtk_container_focus_sort (GtkContainer *container,
- GList *children,
- GtkDirectionType direction);
static gboolean gtk_container_focus_move (GtkContainer *container,
GList *children,
sorted_children = g_list_reverse (sorted_children);
}
else
- sorted_children = gtk_container_focus_sort (container, children, direction);
+ sorted_children = _gtk_container_focus_sort (container, children, direction, NULL);
return_val = gtk_container_focus_move (container, sorted_children, direction);
static GList *
gtk_container_focus_sort_tab (GtkContainer *container,
GList *children,
- GtkDirectionType direction)
+ GtkDirectionType direction,
+ GtkWidget *old_focus)
{
children = g_list_sort (children, tab_compare);
static GList *
gtk_container_focus_sort_up_down (GtkContainer *container,
GList *children,
- GtkDirectionType direction)
+ GtkDirectionType direction,
+ GtkWidget *old_focus)
{
CompareInfo compare;
GList *tmp_list;
- GtkWidget *old_focus;
compare.container = container;
compare.reverse = (direction == GTK_DIR_UP);
- old_focus = find_old_focus (container, children);
+ if (!old_focus)
+ old_focus = find_old_focus (container, children);
+
if (old_focus)
{
GdkRectangle old_allocation;
static GList *
gtk_container_focus_sort_left_right (GtkContainer *container,
GList *children,
- GtkDirectionType direction)
+ GtkDirectionType direction,
+ GtkWidget *old_focus)
{
CompareInfo compare;
GList *tmp_list;
- GtkWidget *old_focus;
compare.container = container;
compare.reverse = (direction == GTK_DIR_LEFT);
+
+ if (!old_focus)
+ old_focus = find_old_focus (container, children);
- old_focus = find_old_focus (container, children);
if (old_focus)
{
GdkRectangle old_allocation;
* @children: a list of descendents of @container (they don't
* have to be direct children.
* @direction: focus direction
+ * @old_focus: widget to use for the starting position, or %NULL
+ * to determine this automatically.
+ * [ Note, this argument isn't used for GTK_DIR_TAB_*,
+ * which is the only @direction we use currently,
+ * so perhaps this argument should be removed ]
*
* Sorts @children in the correct order for focusing with
* direction type @direction.
* with children that aren't suitable for focusing in this direction
* removed.
**/
-static GList *
-gtk_container_focus_sort (GtkContainer *container,
- GList *children,
- GtkDirectionType direction)
+GList *
+_gtk_container_focus_sort (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction,
+ GtkWidget *old_focus)
{
children = g_list_copy (children);
{
case GTK_DIR_TAB_FORWARD:
case GTK_DIR_TAB_BACKWARD:
- return gtk_container_focus_sort_tab (container, children, direction);
+ return gtk_container_focus_sort_tab (container, children, direction, old_focus);
case GTK_DIR_UP:
case GTK_DIR_DOWN:
- return gtk_container_focus_sort_up_down (container, children, direction);
+ return gtk_container_focus_sort_up_down (container, children, direction, old_focus);
case GTK_DIR_LEFT:
case GTK_DIR_RIGHT:
- return gtk_container_focus_sort_left_right (container, children, direction);
+ return gtk_container_focus_sort_left_right (container, children, direction, old_focus);
}
g_assert_not_reached ();
gchar* _gtk_container_child_composite_name (GtkContainer *container,
GtkWidget *child);
void _gtk_container_dequeue_resize_handler (GtkContainer *container);
+GList *_gtk_container_focus_sort (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction,
+ GtkWidget *old_focus);
#ifndef GTK_DISABLE_DEPRECATED
#define gtk_container_border_width gtk_container_set_border_width
#include "gdk/gdkkeysyms.h"
#include "gtkbindings.h"
#include "gtkmain.h"
+#include "gtkmarshalers.h"
#include "gtkmenubar.h"
#include "gtkmenuitem.h"
#include "gtksettings.h"
GdkEventExpose *event);
static void gtk_menu_bar_hierarchy_changed (GtkWidget *widget,
GtkWidget *old_toplevel);
+static void gtk_menu_bar_cycle_focus (GtkMenuBar *menubar,
+ GtkDirectionType dir);
static GtkShadowType get_shadow_type (GtkMenuBar *menubar);
+enum {
+ CYCLE_FOCUS,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
static GtkMenuShellClass *parent_class = NULL;
GtkType
return menu_bar_type;
}
+static guint
+binding_signal_new (const gchar *signal_name,
+ GType itype,
+ GSignalFlags signal_flags,
+ GCallback handler,
+ GSignalAccumulator accumulator,
+ gpointer accu_data,
+ GSignalCMarshaller c_marshaller,
+ GType return_type,
+ guint n_params,
+ ...)
+{
+ va_list args;
+ guint signal_id;
+
+ g_return_val_if_fail (signal_name != NULL, 0);
+
+ va_start (args, n_params);
+
+ signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
+ g_cclosure_new (handler, NULL, NULL),
+ accumulator, accu_data, c_marshaller,
+ return_type, n_params, args);
+
+ va_end (args);
+
+ return signal_id;
+}
+
static void
gtk_menu_bar_class_init (GtkMenuBarClass *class)
{
menu_shell_class->submenu_placement = GTK_TOP_BOTTOM;
+ signals[CYCLE_FOCUS] =
+ binding_signal_new ("cycle_focus",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
+ G_CALLBACK (gtk_menu_bar_cycle_focus),
+ NULL, NULL,
+ _gtk_marshal_VOID__ENUM,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_DIRECTION_TYPE);
+
binding_set = gtk_binding_set_by_class (class);
gtk_binding_entry_add_signal (binding_set,
GDK_Left, 0,
"move_current", 1,
GTK_TYPE_MENU_DIRECTION_TYPE,
GTK_MENU_DIR_CHILD);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Tab, GDK_CONTROL_MASK,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Tab, GDK_CONTROL_MASK,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Tab, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Tab, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
gtk_widget_class_install_style_property (widget_class,
g_param_spec_enum ("shadow_type",
return FALSE;
}
+static GList *
+get_menu_bars (GtkWindow *window)
+{
+ return g_object_get_data (G_OBJECT (window), "gtk-menu-bar-list");
+}
+
+static void
+set_menu_bars (GtkWindow *window,
+ GList *menubars)
+{
+ g_object_set_data (G_OBJECT (window), "gtk-menu-bar-list", menubars);
+}
+
static gboolean
window_key_press_handler (GtkWidget *widget,
GdkEventKey *event,
((event->state & gtk_accelerator_get_default_mod_mask ()) ==
(mods & gtk_accelerator_get_default_mod_mask ())))
{
- GtkMenuBar *menubar;
- GtkMenuShell *menushell;
-
- menubar = GTK_MENU_BAR (data);
- menushell = GTK_MENU_SHELL (menubar);
+ GList *menubars = get_menu_bars (GTK_WINDOW (widget));
- if (menushell->children)
- {
- gtk_signal_emit_by_name (GTK_OBJECT (menushell->children->data),
- "activate_item");
-
- retval = TRUE;
- }
+ menubars = _gtk_container_focus_sort (GTK_CONTAINER (widget), menubars,
+ GTK_DIR_TAB_FORWARD, NULL);
+ if (menubars)
+ {
+ GtkMenuShell *menushell = GTK_MENU_SHELL (menubars->data);
+
+ if (menushell->children)
+ {
+ gtk_signal_emit_by_name (GTK_OBJECT (menushell->children->data),
+ "activate_item");
+ retval = TRUE;
+ }
+
+ g_list_free (menubars);
+ }
}
g_free (accel);
add_to_window (GtkWindow *window,
GtkMenuBar *menubar)
{
- GtkMenuBar *old_menubar;
+ GList *menubars = get_menu_bars (window);
- old_menubar = g_object_get_data (G_OBJECT (window),
- "gtk-menu-bar");
-
- if (old_menubar)
- return; /* ignore this case; app programmer on crack, but
- * shouldn't spew stuff, just don't support the accel
- * for menubar #2
- */
-
- g_object_set_data (G_OBJECT (window),
- "gtk-menu-bar",
- menubar);
-
- g_signal_connect (G_OBJECT (window),
- "key_press_event",
- G_CALLBACK (window_key_press_handler),
- menubar);
+ if (!menubars)
+ {
+ g_signal_connect (G_OBJECT (window),
+ "key_press_event",
+ G_CALLBACK (window_key_press_handler),
+ NULL);
+ }
+
+ set_menu_bars (window, g_list_prepend (menubars, menubar));
}
static void
remove_from_window (GtkWindow *window,
GtkMenuBar *menubar)
{
- g_signal_handlers_disconnect_by_func (G_OBJECT (window),
- G_CALLBACK (window_key_press_handler),
- menubar);
+ GList *menubars = get_menu_bars (window);
+
+ menubars = g_object_get_data (G_OBJECT (window),
+ "gtk-menu-bar-list");
+
+ menubars = g_list_remove (menubars, menubar);
+
+ if (!menubars)
+ {
+ g_signal_handlers_disconnect_by_func (G_OBJECT (window),
+ G_CALLBACK (window_key_press_handler),
+ NULL);
+ }
+
+ set_menu_bars (window, menubars);
}
static void
add_to_window (GTK_WINDOW (toplevel), menubar);
}
+static void
+gtk_menu_bar_cycle_focus (GtkMenuBar *menubar,
+ GtkDirectionType dir)
+{
+ GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menubar));
+
+ if (GTK_WIDGET_TOPLEVEL (toplevel))
+ {
+ GList *menubars = get_menu_bars (GTK_WINDOW (toplevel));
+ GList *current;
+ GtkMenuBar *new;
+
+ menubars = _gtk_container_focus_sort (GTK_CONTAINER (toplevel), menubars,
+ dir, GTK_WIDGET (menubar));
+
+ if (menubars)
+ {
+ current = g_list_find (menubars, menubar);
+ if (current && current->next)
+ new = current->next->data;
+ else
+ new = menubars->data;
+
+ if (new != menubar)
+ {
+ GtkMenuShell *new_menushell = GTK_MENU_SHELL (new);
+
+ if (new_menushell->children)
+ {
+ g_signal_emit_by_name (menubar, "cancel", 0);
+ gtk_signal_emit_by_name (GTK_OBJECT (new_menushell->children->data),
+ "activate_item");
+ }
+ }
+ }
+
+ g_list_free (menubars);
+ }
+}
+
static GtkShadowType
get_shadow_type (GtkMenuBar *menubar)
{
gtk_menu_item_select_timeout (gpointer data)
{
GtkMenuItem *menu_item;
+ GtkWidget *parent;
GDK_THREADS_ENTER ();
menu_item = GTK_MENU_ITEM (data);
-
- gtk_menu_item_popup_submenu (data);
- if (menu_item->timer_from_keypress && menu_item->submenu)
- GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
+
+ parent = GTK_WIDGET (menu_item)->parent;
+
+ if (parent && GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->active)
+ {
+ gtk_menu_item_popup_submenu (data);
+ if (menu_item->timer_from_keypress && menu_item->submenu)
+ GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
+ }
GDK_THREADS_LEAVE ();
if (GTK_IS_WINDOW (toplevel) &&
_gtk_window_activate_key (GTK_WINDOW (toplevel), event))
return TRUE;
+
+ if (menu_shell->parent_menu_shell)
+ return gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent *)event);
return FALSE;
}
#define SCROLLBAR_SPACING(w) (GTK_SCROLLED_WINDOW_GET_CLASS (w)->scrollbar_spacing)
-#define DEFAULT_SCROLLBAR_SPACING 3
+#define DEFAULT_SCROLLBAR_SPACING 0
enum {
PROP_0,
gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
gtk_widget_show (menuitem);
+ menubar = gtk_menu_bar_new ();
+ gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
+ gtk_widget_show (menubar);
+
+ menu = create_menu (2, 10, TRUE);
+
+ menuitem = gtk_menu_item_new_with_label ("Second menu bar");
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
+ gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
+ gtk_widget_show (menuitem);
+
box2 = gtk_vbox_new (FALSE, 10);
gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);